<?php
/**
 * Created by PhpStorm.
 * User: sosyuki
 * Date: 2018/6/28
 * Time: 14:33
 */

namespace Drupal\services_facetapi;


use SearchApiQuery;
use SearchApiQueryFilter;

trait SearchApiFuncTrait {

  /***
   * @param $index
   * @param string $keys
   * @param array $filter
   * @param array $sort
   * @param int|NULL $limit
   * @param int $offset
   *
   * @return array
   * @throws \SearchApiException
   */
  protected function _searchApiResourceRetrieve($index, string $keys = '', array $filter = [], array $sort = [], int $limit = NULL, int $offset = 0) {
    $options = [
      'parse mode' => 'terms',
      'limit' => $limit,
      'offset' => $offset,
    ];

    // Initialize the query object.
    $query = search_api_query($index, $options);
    if (!empty($keys)) {
      $query->keys($keys);
    }
    if (!empty($filter) && is_array($filter)) {
      $query_filter = new SearchApiQueryFilter();
      $this->_searchApiAddFilter($filter, $query_filter);
      $query->filter($query_filter);
    }

    // Also set sorts.
    if (!empty($sort) && is_array($sort)) {
      foreach ($sort as $field => $mode) {
        $query->sort($field, $mode);
      }
    }

    $result = $query->execute();
    $return = $result;
    unset($return['search_api_facets']);
    unset($return['ignored']);
    unset($return['warnings']);
    $this->_searchApiResultAlter($return, $query);
    return $return;
  }

  /**
   * Prepare the query filters for the Search API query object.
   */
  protected function _searchApiAddFilter(array $filter, &$query_filter) {
    if (empty($filter['~and']) && empty($filter['~or'])) {
      $filter = ['~and' => $filter];
    }

    foreach ($filter as $key => $value) {
      if (is_array($value) && !empty($value)) {
        $conjunction = 'AND';
        if ($key == '~or') {
          $conjunction = 'OR';
        }
        $process_filter = new SearchApiQueryFilter($conjunction);
        foreach ($value as $k => $v) {
          if ($k <> '~and' && $k <> '~or') {
            $field_name = $k;
            if (is_array($v) && !empty($v)) {
              $process_filter->condition($field_name, reset($v), $this->_searchApiOperator(key($v)));
            }
            else {
              $process_filter->condition($field_name, $v);
            }
          }
          else {
            $this->_searchApiAddFilter([$k => $v], $process_filter);
          }
        }

        if (!empty($query_filter) && $query_filter instanceof SearchApiQueryFilter) {
          $query_filter->filter($process_filter);
        }
        else {
          $query_filter = $process_filter;
        }
      }
    }
  }

  /**
   * Transform the operator into Search API supported ones.
   */
  protected function _searchApiOperator($operator) {
    $operators = [
      '~gt' => '>',
      '~lt' => '<',
      '~gte' => '>=',
      '~lte' => '<=',
      '~ne' => '<>',
      '~in' => 'IN',
      '~not' => 'NOT IN',
    ];
    return isset($operators[$operator]) ? $operators[$operator] : '=';
  }

  protected function _searchApiResultAlter(&$return, &$query) {
    if ($query instanceof SearchApiQuery) {
      $index = $query->getIndex()->machine_name;
      $searcher_name = 'search_api@' . $index;
      $build = facetapi_build_realm($searcher_name, 'services_facetapi');
      $facets = [];
      foreach ($build as $value => $item) {
        if ('#' != substr($value, 0, 1)) {
          $item[$value]['title'] = $item['#title'];
          $facets[$value] = $item[$value];
        }
      }
      $return['facets'] = array_values($facets);
      if (function_exists('search_api_sorts_search_sorts')) {
        $search_sorts = search_api_sorts_search_sorts($query->getIndex()->machine_name);
        $sorts = [];
        if (!empty($search_sorts)) {
          $qSort = $query->getSort();
          //fix json sort bug
          $default = 0;
          $i = 0;
          foreach ($search_sorts as $sort) {
            $sort = (array) $sort;
            $sort['default_sort'] = (bool) $sort['default_sort'];
            if (isset($qSort[$sort['field']])) {
              $sort['sort'] = (strtolower($qSort[$sort['field']]) == 'asc') ? 'asc' : 'desc';
              $sort['active'] = TRUE;
            }
            else {
              $sort['sort'] = (strtolower($sort['default_order']) == 'asc') ? 'asc' : 'desc';
              $sort['active'] = FALSE;
            }

            if ($sort['default_sort']) {
              $default = $i;
            }

            $sorts[$i] = (array) $sort;
            $i++;
          }

          if (empty($qSort)) {
            $sorts[$default]['active'] = TRUE;
          }

          usort($sorts, 'drupal_sort_weight');
        }
        $return['sorts'] = $sorts;
      }
    }
  }
}
